package dao;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import utils.UtilCollection;
import utils.UtilJackson;
import utils.UtilMath;
import utils.UtilString;
import dao.domain.ConditionFilterClass;
import dao.domain.ConditionFilterField;
import dao.domain.ConvertClass;





    /**
    * @ClassName: ConditionFilterFactory
    * @Description: 根据传入的ConditionFilterClass和
    * @author 宁少林
    * @date 2016年11月8日
    *
    */
public class ConditionFilterFactory {
	
	static Logger logger =LoggerFactory.getLogger(ConditionFilterFactory.class);
	
	public static ConditionFilterClass getConditionFilterClassFromHttpRequest(HttpServletRequest request){
		String filterJson=request.getParameter("filterJson");
		
		if(UtilString.isNullOrEmpty(filterJson)){
			return null;
		}
		ConditionFilterClass filterClass=UtilJackson.me().json2Obj(filterJson, ConditionFilterClass.class);
		return filterClass;
	}
	
	
	    /**
	    * @Title: buildHql
	    * @Description: 根据传入的ConditionFilterClass 和 转换Map, 生成查询条件
	    * 
	    * @param @param filterClass
	    * @param @param convertClassMap
	    * @param @return    
	    * @return String    
	    * @throws
	    */
	public static String buildHql(ConditionFilterClass filterClass,Map<String, ConvertClass> convertClassMap){
		String hql="";
		if(filterClass == null){
			return hql;
		}
		
		//预处理
		String className=filterClass.getClassName()==null?"":filterClass.getClassName();
		
		
		
		// className 为空,返回空查询条件
		String originalClassName=filterClass.getClassName();
		if(filterClass==null || UtilString.isNullOrEmpty(filterClass.getClassName())){
			return "";
		}
		
		//fields 为空,返回空查询条件
		List<ConditionFilterField> fields=filterClass.getFields();
		if(fields==null || fields.size()==0){
			return "";
		}
		
		logger.debug(className);
		
		
		//处理逻辑连接符:如果为空的话，赋值为and,不为空，将最后一个制定的符号，填充到剩余的连接符
		List<String> operatorList=new ArrayList<>();
		List<String> originalOpList=filterClass.getFieldOperators();
		String lastOperator="and";
		int offset=0;//记录赋值的operatList序号
		if(originalOpList!=null){
			for(int x=0;x<originalOpList.size();x++){
				String op=originalOpList.get(x).trim().toLowerCase();
				logger.debug(op);
				if(!op.equalsIgnoreCase("and") && !op.equalsIgnoreCase("or"))
					throw new RuntimeException("筛选条件中的逻辑连接符错误:不为and/or");
				operatorList.add(op);
				lastOperator=op;
				offset++;
			}
		}
		for(int y=offset;y<fields.size()-1;y++){
			operatorList.add(lastOperator);
		}
		logger.debug(operatorList+"");
		
		
		//连接FilterField
		for(int i=0;i<fields.size();i++){
			String hqlPart=buildHqlByFilterField(className,fields.get(i),convertClassMap);
			/*	System.out.println("**************"+hqlPart);*/
			logger.debug("i="+i);
			if(hql.equals("")){
				hql=hqlPart;
			}else{
				hql+=operatorList.get(i-1)+hqlPart;
			}
		}
		
		if(!UtilString.isNullOrEmpty(hql)){
			hql=" where ("+ hql+" )";
		}
			
		return hql;
	}
	
	public static String buildHqlByFilterField(String originalClassName,ConditionFilterField filterField,Map<String, ConvertClass> convertClassMap){
		if(filterField==null ){
			return "";
		}
		
		String originalFieldName=filterField.getFieldName();
		if(UtilString.isNullOrEmpty(originalFieldName)){
			return "";
		}
		
		List<String> valueList=filterField.getValues();
		if(UtilCollection.isNullOrEmpty(valueList)){
			return "";
		}
		
		//记录生成 输出的 条件 类名和域名如 project.name 或者 designer.name
		String outputClassName=null;
		String outputFieldName=null;
		
		ConvertClass convertClass=null;
		if(convertClassMap!=null){
			convertClass=convertClassMap.get(originalClassName);
		}
		
		
		if(convertClass!=null){
			String converFieldName=convertClass.getConvertFieldMap().get(originalFieldName);
			if(!UtilString.isNullOrEmpty(converFieldName)){
				outputClassName=convertClass.getConvertClassName();
				outputFieldName=converFieldName;
			}
		}else{
			outputClassName=originalClassName;
			outputFieldName=originalFieldName;
		}
		
		if(UtilString.isNullOrEmpty(outputClassName,outputFieldName)){
			return "";
		}
		
		//处理FieldOperator
		List<String> originalOpList=filterField.getValueOperators();
		//处理逻辑连接符:如果为空的话，赋值为or,不为空,除指定外,填充剩余or
		List<String> outputOperatorList=new ArrayList<>();
		String lastOperator="or";
		int offset=0;//记录赋值的operatList序号
		if(originalOpList!=null){
			for(int x=0;x<originalOpList.size();x++){
				String op=originalOpList.get(x).trim().toLowerCase();
				logger.debug(op);
				if(!op.equalsIgnoreCase("and") && !op.equalsIgnoreCase("or"))
					throw new RuntimeException("筛选条件中的逻辑连接符错误:不为and/or");
				outputOperatorList.add(op);
				lastOperator=op;
				offset++;
			}
		}
		for(int y=offset;y<valueList.size()-1;y++){
			outputOperatorList.add(lastOperator);
		}
		logger.debug(outputOperatorList+"");
		
		//处理filterType
		String outputFiledType=null;
		if(UtilString.isNullOrEmpty(outputFiledType)){
			outputFiledType="string";
		}else {
			outputFiledType=filterField.getFieldType().trim().toLowerCase();
		}
		
		
		String fiterString="";
				
		for(int i=0;i<valueList.size();i++){
			String queryExpression=valueList.get(i);
			String outputOperator=null;
			if(i>0){
				outputOperator=outputOperatorList.get(i-1);
			}
			
			String hqlPart=query2HqlElement(outputClassName,outputFieldName,outputFiledType,queryExpression);
			//String hqlPart=likeOperator(key,queryExpression);
			if(fiterString.equalsIgnoreCase("")){
				fiterString=hqlPart;
			}else {
				fiterString+=outputOperator+hqlPart;
			}
		}
		fiterString=" ( "+fiterString+" ) ";
	/*	System.out.println(hql);*/
		return fiterString;
	}
	
	//处理查询子条件，根据
		public static String query2HqlElement(String outputClassName,String outputFieldName,String outputFieldType,String queryExpression){
			String key=outputClassName+"."+outputFieldName;
			
			//String operator=field.getFieldOperator();
		
			int index=-1;
			String queryValue;
			String queryValue2;
			queryExpression=queryExpression.trim();
			
			String hqlElement="";
			
			boolean opIsExisted=queryExpression.contains("=")||queryExpression.contains("&")||
					queryExpression.contains(">")||queryExpression.contains("<")||queryExpression.contains("[");
			
			//handle =/'',1.string 2,number
			if((index=queryExpression.indexOf("="))>-1 || !opIsExisted){
				int begin=opIsExisted?1:0;
				queryValue=queryExpression.substring(begin,queryExpression.length()).trim();
				if(outputFieldType.equalsIgnoreCase("string")){
					hqlElement=" ("+key+"= '"+queryValue+"') ";
					logger.debug(hqlElement);
					return hqlElement;
				}
				if(outputFieldType.equalsIgnoreCase("int")){
					int quaryInt=Integer.parseInt(queryValue);
					hqlElement=" ("+key+"="+quaryInt+") ";
					return hqlElement;
				}
				if(outputFieldType.equalsIgnoreCase("long")){
					long quaryLong=Long.parseLong(queryValue);
					hqlElement=" ("+key+"="+quaryLong+") ";
					return hqlElement;
				}
				if(outputFieldType.equalsIgnoreCase("float")){
					float quaryFloat=Float.parseFloat(queryValue);
					hqlElement=" ("+key+"="+quaryFloat+") ";
					return hqlElement;
				}
				//如果 type 未赋值 或是其他值得话，当做string 处理
				hqlElement=" ("+key+"= '"+queryValue+"') ";
				return hqlElement;
			}
			
			//handle like
			if((index=queryExpression.indexOf("&"))>-1){
				queryValue=queryExpression.substring(1,queryExpression.length()).trim();
				hqlElement=" ("+key+" like '%"+queryValue+"%' )";
				logger.debug(hqlElement);
				return hqlElement;
			}
			
			//handle > 非数字,抛出异常
			if((index=queryExpression.indexOf(">"))>-1){
				queryValue=queryExpression.substring(1,queryExpression.length()).trim();
				if(!UtilMath.isNumeric(queryValue)){//非数字，不处理，返回""
					throw new RuntimeException("查询条件错误: "+queryExpression);
				}
				hqlElement=" ("+key+" > "+queryValue+") ";
				logger.debug(hqlElement);
				return hqlElement;
			}
			//handle < 非数字,抛出异常
			if((index=queryExpression.indexOf("<"))>-1){
				queryValue=queryExpression.substring(1,queryExpression.length()).trim();
				if(!UtilMath.isNumeric(queryValue)){//非数字，不处理，返回""
					throw new RuntimeException("查询条件错误: "+queryExpression);
				}
				hqlElement=" ("+key+" < "+queryValue+") ";
				logger.debug(hqlElement);
				return hqlElement;
			}
			
			//handle [] ,非数，返 ""
			logger.debug(queryExpression);
			if(queryExpression.indexOf("[")>-1 && queryExpression.indexOf("]")>-1){
				queryExpression=queryExpression.replace("[", "");
				queryExpression=queryExpression.replace("]", "");
				System.out.println(queryExpression);
				String[] queryValuses=queryExpression.split(",");
				if(queryValuses.length==2){
					String min=queryValuses[0].trim();
					String max=queryValuses[1].trim();
					//System.out.println("min="+min+"********       max="+max);
					if(UtilMath.isNumeric(min) && UtilMath.isNumeric(max)){
						hqlElement=" ("+key+" >= "+min+ " and "+key+" <= "+max+") ";
						return hqlElement;
					}else{
						throw new RuntimeException("查询条件错误: "+queryExpression);
					}
				}
			}
			
			return "";
		}
		
		private static String likeOperator(String key,String value){		
			String condition;
			condition=" ("+key+" like '%"+value+"%') ";		
			return  condition;
		}
	
	
	/**
	 * 根据list 返回 Hql. like "( ( (prject.department like '%一分%') or (prject.department like '%网优%') ) and ( (prject.classByProsssion like '%移动通信%') or (prject.classByProsssion like '%数据交换%') ) "
	 * element=(prject.department like '%一分%')   part=( (prject.department like '%一分%') or (prject.department like '%网优%') 
	 * @param conditionList
	 * @return 无如查询条件，返回null
	 */
	/*public static String buildHqlByList(List<FilterCondition> conditionList){
		
		if(conditionList==null || conditionList.size()==0){
			return "";
		}
		
		String hqlString="";
		for(FilterCondition condition:conditionList){
			String hqlPart=buildHqlByCondition(condition);
			System.out.println("**************"+hqlPart);
			if(hqlString.equals("")){
				hqlString=hqlPart;
			}else{
				hqlString+=" and "+hqlPart;
			}
		}
		
		if(!hqlString.equals(""))
			hqlString=" ( "+hqlString+" )";
		
		logger.debug(hqlString);
		
		return hqlString;
	}
	*/
	//
	/*public static String buildHqlByCondition(FilterCondition condition){
		if(condition==null){
			return "";
		}
		String webClassName=condition.getClassName();
		String webField=condition.getClassField();
		List<String> valueList=condition.getValueArray();
		
		if(webClassName==null ||webField==null || valueList==null || valueList.size()==0){
			return "";
		}
		
		Map<String, WebClassField> fieldMap=Dictionary.WEB_CLASS.get(webClassName);
		
		WebClassField field=fieldMap.get(webField);
		
		//如果字典中未记录 webfield,以前台condition 值生成field,默认为type=string
		if(field==null){
			field=new WebClassField();
			field.setModelClassName(webClassName);
			field.setModelFieldName(webField);
			field.setType("string");
		}
		
		String hql="";
		String key=field.getModelClassName()+"."+field.getModelFieldName();
		String operator=field.getFilterOperator();
				
		for(String queryExpression:valueList){
			
			String hqlPart=query2HqlElement(field,queryExpression);
			//String hqlPart=likeOperator(key,queryExpression);
			if(hql.equalsIgnoreCase("")){
				hql=hqlPart;
			}else {
				hql+="or"+hqlPart;
			}
		}
		hql=" ( "+hql+" ) ";
		System.out.println(hql);
		return hql;
		
		
		
		if(className.equalsIgnoreCase("project") || className.equalsIgnoreCase("department")){
			return projectBuilder(condition);
		}
		
		return "";
	}*/
	
	
	
	
	/*private static String projectBuilder(FilterCondition condition){
		String className=condition.getClassName();
		String classField=condition.getClassField();
		List<String> valueList=condition.getValueArray();
		
		
		String operatorName="like";
		String key=className+"."+classField;
		
		String hql="";
		
		for(String value:valueList){
			String hqlPart=likeOperator(key,value);
			if(hql.equalsIgnoreCase("")){
				hql=hqlPart;
			}else {
				hql+="or"+hqlPart;
			}
		}
		hql=" ( "+hql+" ) ";
		System.out.println(hql);
		return hql;
	}*/
	
	
}
